﻿using Manina.Windows.Forms;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using System.Xml.XPath;

namespace LicenseAutoDetection
{
    // public으로 선언해야 하는 것은 SettingsForm 생성자에서 이 클래스를 사용하기 때문임
    public class Settings
    {
        const string DefaultXml = "LicenseAutoDetection.xml";

        static readonly string DefaultPath = "컴퓨터";
        const Boolean DefaultIncludeWidows = false;
        const Boolean DefaultIncludeHidden = false;
        const Boolean DefaultAutoStart = true;
        static readonly string[] DefaultExt = new string[] { "jpg", "jpeg", "png", "xls", "pdf" };
        const ViewMode DefaultView = ViewMode.Thumbnail;
        const ViewStyle DefaultStyle = ViewStyle.Basic;
        const ThumbSize DefaultThumbSize = ThumbSize.Size96;
        const SearchDepth DefaultSearchDepth = SearchDepth.All;

        const string RootTag = "root";
        const string IgnorePathTag = "ignorePath";
        const string IncludeWindowsTag = "includeWindowsAndProgramFiles";
        const string IncludeHiddenTag = "includeHidden";
        const string AutoStartTag = "autoStart";
        const string ExtTag = "extension";
        const string ViewTag = "view";
        const string StyleTag = "style";
        const string ThumbSizeTag = "thumbnailSize";
        const string SearchDepthTag = "searchDepth";

        static readonly string[] WindowFolders = new string[] {
            Environment.GetFolderPath(Environment.SpecialFolder.Windows),
            "C:\\Program Files",
            Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86)
        };

        XmlDocument xmlDoc;

        public Settings()
        {
            xmlDoc = new XmlDocument();
            string[] ignorePath;
            Boolean includeWindows;
            Boolean includeHidden;
            Boolean autoStart;
            string[] ext;
            ViewMode view;
            ViewStyle style;
            ThumbSize thumbSize;
            SearchDepth searchDepth;

            // 파일이 존재하지 않거나 태그 내용이 잘못된 경우에 대한 처리를 위해 우선 파일을 읽어 태그 값을 읽는다
            // 만약 읽지 못하면 디폴트 값을 가질 것이다. 읽은 값이나 디폴트 값으로 다시 xml 구조를 만든다
            try
            {
                xmlDoc.Load(DefaultXml);
            }
            catch (System.IO.FileNotFoundException)
            {
                // do nothing
            }

            ignorePath = IgnorePath;
            includeWindows = IncludeWindows;
            includeHidden = IncludeHidden;
            autoStart = AutoStart;
            ext = Extension;
            view = View;
            style = Style;
            thumbSize = ThumbnailSize;
            searchDepth = SearchDepth;

            xmlDoc = new XmlDocument();
            xmlDoc.AppendChild(xmlDoc.CreateXmlDeclaration("1.0", "utf-8", "yes"));
            XmlNode root = xmlDoc.CreateElement(RootTag);
            root.AppendChild(xmlDoc.CreateElement(IgnorePathTag));
            root.AppendChild(xmlDoc.CreateElement(IncludeWindowsTag));
            root.AppendChild(xmlDoc.CreateElement(IncludeHiddenTag));
            root.AppendChild(xmlDoc.CreateElement(AutoStartTag));
            root.AppendChild(xmlDoc.CreateElement(ExtTag));
            root.AppendChild(xmlDoc.CreateElement(ViewTag));
            root.AppendChild(xmlDoc.CreateElement(StyleTag));
            root.AppendChild(xmlDoc.CreateElement(ThumbSizeTag));
            root.AppendChild(xmlDoc.CreateElement(SearchDepthTag));
            xmlDoc.AppendChild(root);

            IgnorePath = ignorePath;
            IncludeWindows = includeWindows;
            IncludeHidden = includeHidden;
            AutoStart = autoStart;
            Extension = ext;
            View = view;
            Style = style;
            ThumbnailSize = thumbSize;
            SearchDepth = searchDepth;
        }

        public void Save()
        {
            xmlDoc.Save(DefaultXml);
        }

        public Boolean ExcludeFolder(string path)
        {
            if (IgnorePath.Contains(path))
                return true;

            return !IncludeWindows && WindowFolders.Contains(path);
        }

        public string Path
        {
            get
            {
                return DefaultPath;
            }
        }

        public string[] IgnorePath
        {
            get
            {
                try
                {
                    string IgnorePath = xmlDoc.DocumentElement.SelectSingleNode(IgnorePathTag).InnerText;
                    return string.IsNullOrEmpty(IgnorePath) ? new string[] { } : IgnorePath.Split(',');
                }
                catch
                {
                    return new string[] { };
                }

            }
            set
            {
                try
                {
                    xmlDoc.DocumentElement.SelectSingleNode(IgnorePathTag).InnerText = string.Join(",", value);
                }
                catch
                {
                    // do nothing
                }
            }
        }

        public Boolean IncludeWindows
        {
            set
            {
                xmlDoc.DocumentElement.SelectSingleNode(IncludeWindowsTag).InnerText = value.ToString();
            }
            get
            {
                try
                {
                    return Boolean.Parse(xmlDoc.DocumentElement.SelectSingleNode(IncludeWindowsTag).InnerText);
                }
                catch
                {
                    return DefaultIncludeWidows;
                }
            }
        }

        public Boolean IncludeHidden
        {
            set
            {
                xmlDoc.DocumentElement.SelectSingleNode(IncludeHiddenTag).InnerText = value.ToString();
            }
            get
            {
                try
                {
                    return Boolean.Parse(xmlDoc.DocumentElement.SelectSingleNode(IncludeHiddenTag).InnerText);
                }
                catch
                {
                    return DefaultIncludeHidden;
                }
            }
        }

        public Boolean AutoStart
        {
            set
            {
                const string Tag = "LicenceAutoDetection";
                xmlDoc.DocumentElement.SelectSingleNode(AutoStartTag).InnerText = value.ToString();
                Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Run", true);

                if (value)
                {
                    key.SetValue(Tag, Application.ExecutablePath.ToString());
                }
                else
                {
                    if (key.GetValue(Tag) != null)
                    {
                        key.DeleteValue(Tag);
                    }
                }
            }
            get
            {
                try
                {
                    return Boolean.Parse(xmlDoc.DocumentElement.SelectSingleNode(AutoStartTag).InnerText);
                }
                catch
                {
                    return DefaultAutoStart;
                }
            }
        }

        public string[] Extension
        {
            set
            {
                try
                {
                    xmlDoc.DocumentElement.SelectSingleNode(ExtTag).InnerText = string.Join(",", value);
                }
                catch
                {
                    // do nothing
                }
                
            }
            get
            {
                try
                {
                    string ext = xmlDoc.DocumentElement.SelectSingleNode(ExtTag).InnerText;
                    return string.IsNullOrEmpty(ext) ? new string[] { } : ext.Split(',');
                }
                catch
                {
                    return DefaultExt;
                }
            }
        }

        public ViewMode View
        {
            set
            {
                xmlDoc.DocumentElement.SelectSingleNode(ViewTag).InnerText = value.ToString();
            }
            get
            {
                try
                {
                    string view = xmlDoc.DocumentElement.SelectSingleNode(ViewTag).InnerText;
                    return (ViewMode)Enum.Parse(typeof(ViewMode), view);
                }
                catch
                {
                    return DefaultView;
                }
            }
        }

        public ViewStyle Style
        {
            set
            {
                xmlDoc.DocumentElement.SelectSingleNode(StyleTag).InnerText = value.ToString();
            }
            get
            {
                try
                {
                    return (ViewStyle)Enum.Parse(typeof(ViewStyle), xmlDoc.DocumentElement.SelectSingleNode(StyleTag).InnerText);
                }
                catch
                {
                    return DefaultStyle;
                }
            }
        }

        public ThumbSize ThumbnailSize
        {
            set
            {
                xmlDoc.DocumentElement.SelectSingleNode(ThumbSizeTag).InnerText = value.ToString();
            }
            get
            {
                try
                {
                    return (ThumbSize)Enum.Parse(typeof(ThumbSize), xmlDoc.DocumentElement.SelectSingleNode(ThumbSizeTag).InnerText);
                }
                catch
                {
                    return DefaultThumbSize;
                }
            }
        }

        public SearchDepth SearchDepth
        {
            set
            {
                xmlDoc.DocumentElement.SelectSingleNode(SearchDepthTag).InnerText = value.ToString();
            }
            get
            {
                try
                {
                    return (SearchDepth)Enum.Parse(typeof(SearchDepth), xmlDoc.DocumentElement.SelectSingleNode(SearchDepthTag).InnerText);
                }
                catch
                {
                    return DefaultSearchDepth;
                }
            }
        }
    }
}
